package com.xtjc.recsyslog.netty.analyze;

import cn.hutool.core.util.ArrayUtil;
import com.xtjc.recsyslog.util.ConverUtil;
import com.xtjc.recsyslog.util.YunCrcUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Data
@Slf4j
public class AnalyzeYunCharge {

    private static final String before = "68";
    //序列号域
    private String number1;
    private String number2;
    //加密标志
    private String encryptFlag;
    //帧类型码
    private String msgType;
    //具体数据包
    private String[] data;
    private String[] loginAck;

    public static AnalyzeYunCharge analyzeYunCharge(String[] sourceMsg) {
        AnalyzeYunCharge analyzeYunCharge = new AnalyzeYunCharge();
        analyzeYunCharge.setNumber1(sourceMsg[0]);
        analyzeYunCharge.setNumber2(sourceMsg[1]);
        analyzeYunCharge.setEncryptFlag(sourceMsg[2]);
        analyzeYunCharge.setMsgType(sourceMsg[3]);
        String[] data = new String[sourceMsg.length - 4];
        System.arraycopy(sourceMsg, 4, data, 0, sourceMsg.length - 4);
        analyzeYunCharge.setData(data);
        return analyzeYunCharge;
    }

    /**
     * 充电桩认证应答模式
     *
     * @param data   接收的数据
     * @param status true 成功 false 失败
     * @return
     */
    public static String[] loginAck(AnalyzeYunCharge data, boolean status) {
        String before = "68";
        String number1 = data.getNumber1();
        String number2 = data.getNumber2();
        String encryptFlag = data.getEncryptFlag();
        String type = "02";//登录认证应答
        String[] sn = ArrayUtil.sub(data.getData(), 0, 7);
        String loginStatus = status ? "00" : "01";
        String[] body = ArrayUtil.newArray(String.class, sn.length + 5);
        body[0] = number1;
        body[1] = number2;
        body[2] = encryptFlag;
        body[3] = type;
        System.arraycopy(sn, 0, body, 4, sn.length);
        body[sn.length + 4] = loginStatus;
        byte[] crcData = YunCrcUtil.calculateCrc(ConverUtil.hexArrayToByteArray(body));
        byte lowByte = crcData[1];
        byte hiByte = crcData[0];

        int length = sn.length + 9;
        String[] loginAck = ArrayUtil.newArray(String.class, length);
        loginAck[0] = before;
        loginAck[1] = String.format("%02X", body.length);
        loginAck[2] = number1;
        loginAck[3] = number2;
        loginAck[4] = encryptFlag;
        loginAck[5] = type;
        System.arraycopy(sn, 0, loginAck, 6, sn.length);
        loginAck[sn.length + 6] = loginStatus;
        loginAck[sn.length + 7] = ConverUtil.byteToHex(lowByte);
        loginAck[sn.length + 8] = ConverUtil.byteToHex(hiByte);
        return loginAck;
    }

    /**
     * 心跳应答
     *
     * @param data
     * @return
     */
    public static String[] heartBeatAck(AnalyzeYunCharge data) {
        String before = "68";
        String number1 = data.getNumber1();
        String number2 = data.getNumber2();
        String encryptFlag = data.getEncryptFlag();
        String type = "04";//心跳包应答
        String[] sn = ArrayUtil.sub(data.getData(), 0, 7);
        String gunNumber = data.getData()[7];
        String heartbeatResponse = "00";
        String[] body = ArrayUtil.newArray(String.class, sn.length + 6);
        body[0] = number1;
        body[1] = number2;
        body[2] = encryptFlag;
        body[3] = type;
        System.arraycopy(sn, 0, body, 4, sn.length);
        body[sn.length + 4] = gunNumber;
        body[sn.length + 5] = heartbeatResponse;
        byte[] crcData = YunCrcUtil.calculateCrc(ConverUtil.hexArrayToByteArray(body));
        byte lowByte = crcData[1];
        byte hiByte = crcData[0];
        int length = sn.length + 10;
        String[] heartBeatAck = ArrayUtil.newArray(String.class, length);
        heartBeatAck[0] = before;
        heartBeatAck[1] = String.format("%02X", body.length);
        heartBeatAck[2] = number1;
        heartBeatAck[3] = number2;
        heartBeatAck[4] = encryptFlag;
        heartBeatAck[5] = type;
        System.arraycopy(sn, 0, heartBeatAck, 6, sn.length);
        heartBeatAck[sn.length + 6] = gunNumber;
        heartBeatAck[sn.length + 7] = heartbeatResponse;
        heartBeatAck[sn.length + 8] = ConverUtil.byteToHex(lowByte);
        heartBeatAck[sn.length + 9] = ConverUtil.byteToHex(hiByte);
        return heartBeatAck;
    }

    /**
     * 计费模型验证请求应答
     *
     * @param data
     * @param status 验证通过true 验证失败false
     * @return
     */
    public static String[] chargeModelCheckAck(AnalyzeYunCharge data, boolean status) {
        String before = "68";
        String number1 = data.getNumber1();
        String number2 = data.getNumber2();
        String encryptFlag = data.getEncryptFlag();
        String type = "06";//计费模型验证请求应答
        String[] sn = ArrayUtil.sub(data.getData(), 0, 7);
        String chargeModel1 = data.getData()[7];
        String chargeModel2 = data.getData()[8];
        String checkFlag = status ? "00" : "01";
        String[] body = ArrayUtil.newArray(String.class, sn.length + 7);
        body[0] = number1;
        body[1] = number2;
        body[2] = encryptFlag;
        body[3] = type;
        System.arraycopy(sn, 0, body, 4, sn.length);
        body[sn.length + 4] = chargeModel1;
        body[sn.length + 5] = chargeModel2;
        body[sn.length + 6] = checkFlag;
        byte[] crcData = YunCrcUtil.calculateCrc(ConverUtil.hexArrayToByteArray(body));
        byte lowByte = crcData[1];
        byte hiByte = crcData[0];
        int length = sn.length + 11;
        String[] chargeModelAck = ArrayUtil.newArray(String.class, length);
        chargeModelAck[0] = before;
        chargeModelAck[1] = String.format("%02X", body.length);
        chargeModelAck[2] = number1;
        chargeModelAck[3] = number2;
        chargeModelAck[4] = encryptFlag;
        chargeModelAck[5] = type;
        System.arraycopy(sn, 0, chargeModelAck, 6, sn.length);
        chargeModelAck[sn.length + 6] = chargeModel1;
        chargeModelAck[sn.length + 7] = chargeModel2;
        chargeModelAck[sn.length + 8] = checkFlag;
        chargeModelAck[sn.length + 9] = ConverUtil.byteToHex(lowByte);
        chargeModelAck[sn.length + 10] = ConverUtil.byteToHex(hiByte);
        log.info("计费模型验证请求应答:{}",ArrayUtil.toString(chargeModelAck));
        return chargeModelAck;
    }

    /**
     * 计费模型请求应答
     *
     * @param data
     * @return
     */
    public static String[] chargeModelAck(AnalyzeYunCharge data) {
        String before = "68";
        String number1 = data.getNumber1();
        String number2 = data.getNumber2();
        String encryptFlag = data.getEncryptFlag();
        String type = "0A";//计费模型请求应答
        String[] sn = ArrayUtil.sub(data.getData(), 0, 7);
        String chargeModel1 = "01";
        String chargeModel2 = "07";
        String[] chargeRate_1 = {"40", "0D", "03", "00"};//2.00
        String[] chargeRate_2 = {"40", "0D", "03", "00"};
        String[] chargeRate_3 = {"40", "0D", "03", "00"};
        String[] chargeRate_4 = {"40", "0D", "03", "00"};
        String[] serverRate_1 = {"9C", "40", "00", "00"};//0.16
        String[] serverRate_2 = {"9C", "40", "00", "00"};
        String[] serverRate_3 = {"9C", "40", "00", "00"};
        String[] serverRate_4 = {"9C", "40", "00", "00"};
        String[] body = ArrayUtil.newArray(String.class, 2 + 1 + 1 + 7 + 2 + 32 + 1 + 48);
        body[0] = number1;
        body[1] = number2;
        body[2] = encryptFlag;
        body[3] = type;
        System.arraycopy(sn, 0, body, 4, sn.length);
        body[11] = chargeModel1;
        body[12] = chargeModel2;
        System.arraycopy(chargeRate_1, 0, body, 13, chargeRate_1.length);
        System.arraycopy(serverRate_1, 0, body, 17, serverRate_1.length);
        System.arraycopy(chargeRate_2, 0, body, 21, chargeRate_2.length);
        System.arraycopy(serverRate_2, 0, body, 25, serverRate_2.length);
        System.arraycopy(chargeRate_3, 0, body, 29, chargeRate_3.length);
        System.arraycopy(serverRate_3, 0, body, 33, serverRate_3.length);
        System.arraycopy(chargeRate_4, 0, body, 37, chargeRate_4.length);
        System.arraycopy(serverRate_4, 0, body, 41, serverRate_4.length);
        body[45] = "00";
        for (int i = 1; i < 49; i++) {
            body[45 + i] = "00";
        }
        byte[] crcData = YunCrcUtil.calculateCrc(ConverUtil.hexArrayToByteArray(body));
        byte lowByte = crcData[1];
        byte hiByte = crcData[0];
        int length = 1 + 1 + 2 + 1 + 1 + 7 + 2 + 32 + 1 + 48 + 2;
        String[] chargeModelAck = ArrayUtil.newArray(String.class, length);
        chargeModelAck[0] = before;
        chargeModelAck[1] = String.format("%02X", body.length);
        System.arraycopy(body, 0, chargeModelAck, 2, body.length);
        chargeModelAck[length - 2] = ConverUtil.byteToHex(lowByte);
        chargeModelAck[length - 1] = ConverUtil.byteToHex(hiByte);
        log.info("计费模型请求应答:{}",ArrayUtil.toString(chargeModelAck));
        return chargeModelAck;
    }


    /**
     * 交易记录确认
     *
     * @param data
     * @return
     */
    public static String[] tradingAck(AnalyzeYunCharge data) {
        String[] number = {data.getNumber1(), data.getNumber2()};
        String encryptFlag = "00";
        String type = "40";//交易记录确认
        String[] txnSeqNum = ArrayUtil.sub(data.getData(), 0, 16);
        String[] body = ArrayUtil.newArray(String.class, 21);
        System.arraycopy(number, 0, body, 0, number.length);
        body[2] = encryptFlag;
        body[3] = type;
        System.arraycopy(txnSeqNum, 0, body, 4, txnSeqNum.length);
        body[20] = "00";
        return commend(body);
    }

    private static String[] commend(String[] body) {
        byte[] crcData = YunCrcUtil.calculateCrc(ConverUtil.hexArrayToByteArray(body));
        byte lowByte = crcData[1];
        byte hiByte = crcData[0];
        int length = body.length + 4;
        String[] resAck = ArrayUtil.newArray(String.class, body.length + 4);
        resAck[0] = before;
        resAck[1] = String.format("%02X", body.length);
        System.arraycopy(body, 0, resAck, 2, body.length);
        resAck[length - 2] = ConverUtil.byteToHex(lowByte);
        resAck[length - 1] = ConverUtil.byteToHex(hiByte);
        return resAck;
    }

}
